Promise 的使用時機就是適合來解決非同步的事件,非同步的事件通常都是 ajax 的事件,但其實除了 ajax 以外還有其他的喔~!
例如說 setTimeout 也是一種非同步事件,不過還是以大家最熟悉的 ajax 事件來進行說明~!
const url = 'https://randomuser.me/api/';
$.ajax({
url: url
}).done(function (res) {
console.log(res);
});
可以看到這個是很簡易的 jQuery ajax 的寫法,我只有撰寫了 url 向遠端位置請求資料,然後再把資料印出來!
當然 jQuery 官網也有很多種寫法~例如 直接在屬性中添加 success 屬性的,或是加入不同的 Content-Type 的等等。
$.ajax({
url: 'https://randomuser.me/api/',
dataType: 'json',
success: function(data) {
console.log(data);
}
});
但目的都是為了從遠端取得資料回來~
那麼我們再來看看關注現在要打的這隻 API 是做甚麼~
很明顯,這個就是你針對他們的 API 要資料以後,他會回傳給你 result 的 json 格式資料。
內容就如同他們官網的顯示,會隨機產生使用者資料給你。
那我們實際來執行看看!
的確就跟預期的一樣!有出現官網上所說的資料格式~
那麼現在我們來修改一下程式碼~變成下面這樣
const url = 'https://randomuser.me/api/';
let data = {};
$.ajax({
url: url,
}).done(function (res) {
console.log(res);
data = res.results;
});
console.log(data);
各位覺得 data 的資料會是怎麼樣呢?
答案:
答案就是還是維持空物件喔!
原因很簡單,因為非同步的事件會先放到事件佇列,等其他同步的程式碼執行完之後,再依順序執行。
所以這邊 ajax 事件雖然有先放到事件佇列中,但還沒跟遠端取回資料,自然就還沒有辦法再最後面的 log 給印出來。
那麼要如何才能正確印出來呢?
最快速簡單的做法就是把 log 移進去 done 的 function Block 裡面。
const url = 'https://randomuser.me/api/';
let data = {};
$.ajax({
url: url,
}).done(function (res) {
console.log(res);
data = res.results;
console.log(data);
});
各位也可以練習看看這樣子的寫法喔!
那其實這樣寫,每次重新整理阿
你會發現都會取得隨機不同的資料,如果我希望再取得第一次資料以後,又再取得同一個人的資料的話該怎麼半呢?
我們可以看到他的官方文件中,有一個可以帶入 seed 的參數,也就是每一筆使用者資料,都有一個特定的 seed 參數。
我們需要在第一次取得資料之後,又需要在執行完之後取得第二次的資料
那我們的寫法就會是~
const url = 'https://randomuser.me/api/';
let data = {};
$.ajax({
url: url,
}).done(function (res) {
console.log(res);
data = res.results;
const seed = res.info.seed;
console.log('seed', seed);
console.log('data', data);
console.log('res', res);
$.ajax({
url: `${url}?seed=${seed}`,
}).done(function (res2) {
console.log('res2', res2);
const res2Seed = res2.info.seed;
console.log(seed === res2Seed);
});
});
好~這樣就可以完成我們的需求對吧!
但又要第三次呢?第四次呢?
發現問題了嗎? 如果我們要做特定的處理,就必須等到非同步結束以後才能進行,這樣會造成越來越多 巢狀 以及程式碼繁亂不好維護的問題!
而使用 Promise 的好處之一就是可以解決這個問題~
那這邊也來簡單介紹一下,非同步的常見問題
那我們使用 axios 這個 Promise 套件進行剛剛取得遠端資料的效果並同時解決 1 / 2 / 3 的問題
axios.get(url)
.then((res) => {
console.log(1, res);
});
當使用 axios 的時候首先要先決定要使用 get 還是 post,之後最簡單的一樣就是只帶入 url 。
然後利用 then 這個方法去串接,確保非同步行為已經完成!
那麼如果要像剛剛一樣,在第一次取完以後要進行第二次非同步事件,Promise 的行為會先 return 第二次的請求開頭,並且在下一次的 then 做接收。
axios.get(url)
.then((res) => {
console.log(1, res);
const seed = res.data.info.seed;
return axios.get(`${url}?seed=${seed}`);
})
.then((res) => {
console.log(2, res);
});
Promise 裡面有一個 all 的語法,會同時分別針對不同的 url 進行請求,並且等到都完成拿到結果之後,在進行下一步。
Promise.all([axios.get(url), axios.get(url)])
.then(([res1, res2]) => {
console.log(1, res1);
console.log(2, res2);
});
透過陣列的方式傳入 非同步行為,並且回傳一個陣列包含兩個非同步行為的結果。
以上就是使用 Promise 的原因,以及一些簡單的範例介紹,如果沒有問題的話就可以繼續往後續的文章嚕!汪汪~